home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 12 / Example 12.3 / particles.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-06-30  |  6.0 KB  |  210 lines

  1. #include "particles.h"
  2.  
  3. DWORD FtoDword(float f){return *((DWORD*)&f);}
  4.  
  5. //Global Particle Textures
  6. IDirect3DTexture9* starTexture = NULL;
  7.  
  8. struct PARTICLE_VERTEX
  9. {
  10.     D3DXVECTOR3 position;
  11.     D3DCOLOR color;
  12.     static const DWORD FVF;
  13. };
  14.  
  15. const DWORD PARTICLE_VERTEX::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
  16.  
  17. int numParticles = 2048;
  18. IDirect3DVertexBuffer9* particleBuffer = NULL;
  19. DWORD bufferOffset = 0;
  20.  
  21. void LoadParticleResources(IDirect3DDevice9 *Dev)
  22. {
  23.     Dev->CreateVertexBuffer(numParticles * sizeof(PARTICLE_VERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_POINTS | D3DUSAGE_WRITEONLY,
  24.                             PARTICLE_VERTEX::FVF, D3DPOOL_DEFAULT, &particleBuffer, NULL);
  25.  
  26.     //Load textures
  27.     D3DXCreateTextureFromFile(Dev, "textures/star.dds", &starTexture);
  28. }
  29.  
  30. void UnloadParticleResources()
  31. {
  32.     if(particleBuffer)
  33.         particleBuffer->Release();
  34.     particleBuffer = NULL;
  35.  
  36.     //Release textures
  37.     if(starTexture)starTexture->Release();
  38.  
  39.     starTexture = NULL;
  40. }
  41.  
  42. //////////////////////////////////////////////////////////////////////////////////////////////
  43. //                                PARTICLE_SYSTEM                                                //
  44. //////////////////////////////////////////////////////////////////////////////////////////////
  45.  
  46. PARTICLE_SYSTEM::PARTICLE_SYSTEM(IDirect3DDevice9 *Dev) : EFFECT(Dev)
  47. {
  48.     m_pTexture = NULL;
  49.     m_blendMode = D3DBLEND_ONE;
  50.     m_particleSize = 3.0f;
  51. }
  52.  
  53. PARTICLE_SYSTEM::~PARTICLE_SYSTEM()
  54. {
  55.     //Delete all particles
  56.     for(int i=0;i<m_particles.size();i++)
  57.         delete m_particles[i];
  58.     m_particles.clear();
  59. }
  60.  
  61. void PARTICLE_SYSTEM::Update(float timeDelta)
  62. {
  63.     
  64. }
  65.  
  66. void PARTICLE_SYSTEM::Render()
  67. {
  68.     if(m_particles.empty() || particleBuffer == NULL)return;
  69.  
  70.     PreRender();
  71.  
  72.     m_pDevice->SetTexture(0, m_pTexture);
  73.     m_pDevice->SetFVF(PARTICLE_VERTEX::FVF);
  74.     m_pDevice->SetStreamSource(0, particleBuffer, 0, sizeof(PARTICLE_VERTEX));
  75.  
  76.     int batchSize = 512;
  77.     for(int i=0;i<m_particles.size();i+=batchSize)
  78.         RenderBatch(i, batchSize);
  79.  
  80.     PostRender();
  81. }
  82.  
  83. void PARTICLE_SYSTEM::RenderBatch(int start, int batchSize)
  84. {
  85.     //If we will reach the end of the vertex buffer, start over
  86.     if(bufferOffset + batchSize >= numParticles)bufferOffset = 0;
  87.  
  88.     //Lock the vertex buffer
  89.     PARTICLE_VERTEX *p = NULL;
  90.     particleBuffer->Lock(bufferOffset * sizeof(PARTICLE_VERTEX), 
  91.                          batchSize, (void**)&p, 
  92.                          bufferOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);
  93.  
  94.     int particlesRendered = 0;
  95.     for(int i=start;i<m_particles.size() && i < start + batchSize;i++)
  96.         if(!m_particles[i]->dead)
  97.         {
  98.             p->position = m_particles[i]->position;
  99.             p->color = m_particles[i]->color;
  100.             p++;
  101.             particlesRendered++;
  102.         }
  103.  
  104.     particleBuffer->Unlock();
  105.  
  106.     //Render batch 
  107.     if(particlesRendered > 0)
  108.         m_pDevice->DrawPrimitive(D3DPT_POINTLIST, bufferOffset, particlesRendered);
  109.  
  110.     //Increase offset
  111.     bufferOffset += batchSize;
  112. }
  113.  
  114. bool PARTICLE_SYSTEM::isDead()
  115. {
  116.     return true;
  117. }
  118.  
  119. void PARTICLE_SYSTEM::PreRender()
  120. {
  121.     m_pDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, true);
  122.     m_pDevice->SetRenderState(D3DRS_POINTSCALEENABLE, true);
  123.     m_pDevice->SetRenderState(D3DRS_POINTSIZE, FtoDword(m_particleSize));
  124.     m_pDevice->SetRenderState(D3DRS_POINTSCALE_A, FtoDword(0.0f));
  125.     m_pDevice->SetRenderState(D3DRS_POINTSCALE_B, FtoDword(0.0f));
  126.     m_pDevice->SetRenderState(D3DRS_POINTSCALE_C, FtoDword(1.0f));
  127.     m_pDevice->SetRenderState(D3DRS_LIGHTING, false);
  128.  
  129.     m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  130.     m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  131.     m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
  132.     m_pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  133.     m_pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  134.     m_pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
  135.  
  136.     m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
  137.     m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  138.     m_pDevice->SetRenderState(D3DRS_DESTBLEND, m_blendMode);
  139.     m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, false);
  140. }
  141.  
  142. void PARTICLE_SYSTEM::PostRender()
  143. {
  144.     m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
  145.     m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, true);
  146.  
  147.     m_pDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, false);
  148.     m_pDevice->SetRenderState(D3DRS_POINTSCALEENABLE, false);
  149. }
  150.  
  151. //////////////////////////////////////////////////////////////////////////////////////////////
  152. //                                MAGIC SHOWER                                                //
  153. //////////////////////////////////////////////////////////////////////////////////////////////
  154.  
  155. MAGIC_SHOWER::MAGIC_SHOWER(IDirect3DDevice9 *Dev, int noParticles, D3DXVECTOR3 _origin) : PARTICLE_SYSTEM(Dev)
  156. {
  157.     m_origin = _origin;
  158.  
  159.     //Add initial m_particles
  160.     for(int i=0;i<noParticles;i++)
  161.     {
  162.         PARTICLE *p = new PARTICLE();
  163.         memset(p, 0, sizeof(PARTICLE));
  164.         p->time_to_live = rand()%5000 / 1000.0f;
  165.         p->dead = true;
  166.         p->acceleration = D3DXVECTOR3(0.0f, -0.75f, 0.0f);
  167.         m_particles.push_back(p);
  168.     }
  169.  
  170.     //Set texture
  171.     m_pTexture = starTexture;
  172. }
  173.  
  174. void MAGIC_SHOWER::Update(float timeDelta)
  175. {
  176.     for(int i=0;i<m_particles.size();i++)
  177.     {
  178.         //Update live particles
  179.         m_particles[i]->time_to_live -= timeDelta;
  180.         m_particles[i]->velocity += m_particles[i]->acceleration * timeDelta;
  181.         m_particles[i]->position += m_particles[i]->velocity * timeDelta;
  182.         m_particles[i]->color.a = m_particles[i]->time_to_live / 5.0f;
  183.  
  184.         //Re-spawn dead particles
  185.         if(m_particles[i]->time_to_live <= 0.0f)
  186.         {
  187.             m_particles[i]->position = m_origin;
  188.             
  189.             //Random direction
  190.             m_particles[i]->velocity = D3DXVECTOR3((rand()%2000 / 1000.0f) - 1.0f,
  191.                                                  (rand()%2000 / 1000.0f) - 1.0f,
  192.                                                  (rand()%2000 / 1000.0f) - 1.0f);
  193.  
  194.             D3DXVec3Normalize(&m_particles[i]->velocity, &m_particles[i]->velocity);
  195.             m_particles[i]->velocity *= 2.0f;
  196.  
  197.             //Random color
  198.             m_particles[i]->color = D3DXCOLOR(rand()%1000 / 1000.0f, rand()%1000 / 1000.0f, rand()%1000 / 1000.0f, 1.0f);
  199.  
  200.             //Random life span
  201.             m_particles[i]->time_to_live = rand()%4000 / 1000.0f + 1.0f;
  202.             m_particles[i]->dead = false;
  203.         }
  204.     }
  205. }
  206.  
  207. bool MAGIC_SHOWER::isDead()
  208. {
  209.     return false;
  210. }